import time
import logging
from setting import setting
from package.connector.redis_db import rdb
from package.connector.sql_db import db
from package.connector.elastic_db import es_db
from model.model import Crud, Configure, User, Role
from builtin.config import Config, RoleMap
from builtin.index import Template, Component
from builtin.user import ADMIN_USER, SYSTEM_USER
from builtin.role import ADMIN_ROLE, THIRD_ROLE


logger = logging.getLogger('system')


def initialize_table():
    """初始化数据库表信息"""
    Crud.metadata.drop_all(bind=db.engine)
    Crud.metadata.create_all(bind=db.engine)


def initialize_configure():
    with db.SessionLocal() as s:
        is_initialized = s.query(Configure).first()
        if is_initialized:
            return
        configures = [Configure(**configure) for configure in Config]
        configures.append(Configure(**RoleMap))  # 权限地图

        s.add_all(configures)
        s.commit()


def initialize_template():
    for template in Template:
        es_db.client.indices.put_template(name=template['name'], body=template['template'])
        is_exists = es_db.client.indices.exists(index=template['name'])
        if not is_exists:
            es_db.client.indices.create(index=template['name'])
    
    for component_name, body in Component.items():  # 公共组件
        es_db.client.cluster.put_component_template(component_name, body)


def initialize_user():
    with db.SessionLocal() as s:
        user_initial = s.query(User).filter().first()
        role_initial = s.query(Role).filter().first()
        if user_initial or role_initial:
            return

        admin = User(**ADMIN_USER)
        system = User(**SYSTEM_USER)

        super_role = Role(**ADMIN_ROLE)
        third_role = Role(**THIRD_ROLE)

        s.add_all([admin, system, super_role, third_role])

        admin.roles.append(super_role)
        system.roles.append(super_role)
        s.commit()


def load_cache():
    """需要加载到redis中的缓存信息"""
    from router.auth.view import ApikeyView
    from router.configure.view import ConfigureView
    from router.user.view import AuthorizationView

    with db.SessionLocal() as s:
        ApikeyView.load_database2cache(s)
        ConfigureView.load_database2cache(s)
        AuthorizationView.load_database2cache(s)


def init():
    """系统初次启动时需要初始化内置数据"""
    initialize_table()
    initialize_configure()
    initialize_user()
    load_cache()


def dependency():
    """数据库或其他依赖"""
    while True:
        if db.verify():
            break

        logger.warning('wait database to start ...')
        time.sleep(5)
    
    while True:
        if rdb.verify():
            break

        logger.warning('wait redis to start ...')
        time.sleep(5)
    
    # while True:
    #     if es_db.verify():
    #         break

        logger.warning('wait elasticsearch to start ...')
        time.sleep(5)

if __name__ == '__main__':
    db.init(url=setting.pg_uri)
    rdb.init(host=setting.redis_host, password=setting.redis_password)
    es_db.init(hosts=setting.elasticsearch_hosts, http_auth=setting.elasticsearch_auth)

    dependency()
    init()
